
#include "EnvCell.h"
#include <stdio.h>
#include <pthread.h>


using namespace std;

EnvCell::EnvCell() {
    pthread_mutex_lock(&particleContainerLocker);
    if (m_ParticleContainer.size() != 0) {
        cleanCell();
    }
    numAgentsPresent = 0;
    pthread_mutex_unlock(&particleContainerLocker);
}

EnvCell::~EnvCell() {
    pthread_mutex_lock(&particleContainerLocker);
    cleanCell();
    pthread_mutex_unlock(&particleContainerLocker);
}

void EnvCell::cleanCell() {

    while (getNumParticles() != 0) {
        delete m_ParticleContainer.at(0);
        m_ParticleContainer.at(0) = 0;
        m_ParticleContainer.erase(m_ParticleContainer.begin());
    }
}

Particle* EnvCell::takeParticle() {

    Particle* tmpParticle;

    pthread_mutex_lock(&particleContainerLocker);
    if (getNumParticles() == 0) {
        tmpParticle = NULL;
    } else {
        int containerSize = m_ParticleContainer.size();
        containerSize--; // Vectors begin at index 0
        tmpParticle = m_ParticleContainer.at(containerSize);
        tmpParticle = new Particle(tmpParticle->getID());
        delete m_ParticleContainer.at(containerSize);
        m_ParticleContainer.erase(m_ParticleContainer.begin() + containerSize);
    }
    pthread_mutex_unlock(&particleContainerLocker);
    return tmpParticle;
}

void EnvCell::placeParticle(Particle* newParticle) {
    pthread_mutex_lock(&particleContainerLocker);
    m_ParticleContainer.push_back(newParticle);
    pthread_mutex_unlock(&particleContainerLocker);
}

void EnvCell::printContainer() {

    Particle* tmpParticle;
    pthread_mutex_lock(&particleContainerLocker);
    for (int index = 0; index < getNumParticles(); index++) {
        tmpParticle = m_ParticleContainer.at(index);
        printf("Particle %d has ID of: %d\n", index, tmpParticle->getID());
    }
    pthread_mutex_unlock(&particleContainerLocker);
}

vector<int> EnvCell::accountCell(vector<int> assignedIDs) {

    Particle* tmpParticle;
    int tmpID;
    bool ID_Found = false;

    pthread_mutex_lock(&particleContainerLocker);
    if (m_ParticleContainer.size() == 0) {
        pthread_mutex_unlock(&particleContainerLocker);
        return assignedIDs;
    } else {
        for (int index = 0; index < getNumParticles(); index++) {
            tmpParticle = m_ParticleContainer.at(index);
            tmpID = tmpParticle->getID();
            for (int vectorIndex = 0; vectorIndex < assignedIDs.size(); vectorIndex++) {
                if (assignedIDs.at(vectorIndex) == tmpID) {
                    assignedIDs.erase(assignedIDs.begin() + vectorIndex);
                    ID_Found = true;
                    break;
                }
            }
            if (!ID_Found) {
                printf("ERROR: EnvCell::accountCell could not find ID: %d\n", tmpID);
            }
        }
        pthread_mutex_unlock(&particleContainerLocker);
        return assignedIDs;
    }

}

void EnvCell::agentArrived(){
    pthread_mutex_lock(&agentPresentLocker);
    numAgentsPresent ++; 
    pthread_mutex_unlock(&agentPresentLocker);
}

void EnvCell::agentDeparted(){
    pthread_mutex_lock(&agentPresentLocker);
    numAgentsPresent --; 
    pthread_mutex_unlock(&agentPresentLocker);
}

pthread_mutex_t EnvCell::agentPresentLocker;
pthread_mutex_t EnvCell::particleContainerLocker;